home *** CD-ROM | disk | FTP | other *** search
- /* $Id: tess.c,v 1.3 1996/11/12 01:23:02 brianp Exp $ */
-
- /*
- * Mesa 3-D graphics library
- * Version: 2.0
- * Copyright (C) 1995-1996 Brian Paul
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
- /*
- * $Log: tess.c,v $
- * Revision 1.3 1996/11/12 01:23:02 brianp
- * added test to prevent free(vertex) when vertex==NULL in delete_contours()
- *
- * Revision 1.2 1996/10/22 22:57:19 brianp
- * better error handling in gluBegin/EndPolygon() from Erich Eder
- *
- * Revision 1.1 1996/09/27 01:19:39 brianp
- * Initial revision
- *
- */
-
-
- /*
- * This file is part of the polygon tesselation code contributed by
- * Bogdan Sikorski
- */
-
-
- #include <math.h>
- #include <stdlib.h>
- #include "tess.h"
-
-
-
- extern void tess_test_polygon(GLUtriangulatorObj *);
- extern void tess_find_contour_hierarchies(GLUtriangulatorObj *);
- extern void tess_handle_holes(GLUtriangulatorObj *);
- extern void tess_tesselate(GLUtriangulatorObj *);
- extern void tess_tesselate_with_edge_flag(GLUtriangulatorObj *);
- static void delete_contours(GLUtriangulatorObj *);
-
- void init_callbacks(tess_callbacks *callbacks)
- {
- callbacks->begin = ( void (*)(GLenum) ) 0;
- callbacks->edgeFlag = ( void (*)(GLboolean) ) 0;
- callbacks->vertex = ( void (*)(void*) ) 0;
- callbacks->end = ( void (*)(void) ) 0;
- callbacks->error = ( void (*)(GLenum) ) 0;
- }
-
- void tess_call_user_error(GLUtriangulatorObj *tobj,
- GLenum gluerr)
- {
- if(tobj->error==GLU_NO_ERROR)
- tobj->error=gluerr;
- if(tobj->callbacks.error!=NULL)
- (tobj->callbacks.error)(gluerr);
- }
-
- GLUtriangulatorObj* gluNewTess( void )
- {
- GLUtriangulatorObj *tobj;
-
- if((tobj=(GLUtriangulatorObj *)
- malloc(sizeof(struct GLUtriangulatorObj)))==NULL)
- return NULL;
- tobj->contours=tobj->last_contour=NULL;
- init_callbacks(&tobj->callbacks);
- tobj->error=GLU_NO_ERROR;
- tobj->current_polygon=NULL;
- tobj->contour_cnt=0;
- return tobj;
- }
-
-
- void gluTessCallback( GLUtriangulatorObj *tobj, GLenum which,
- void (*fn)() )
- {
- switch(which)
- {
- case GLU_BEGIN:
- tobj->callbacks.begin = (void (*)(GLenum)) fn;
- break;
- case GLU_EDGE_FLAG:
- tobj->callbacks.edgeFlag = (void (*)(GLboolean)) fn;
- break;
- case GLU_VERTEX:
- tobj->callbacks.vertex = (void (*)(void *)) fn;
- break;
- case GLU_END:
- tobj->callbacks.end=fn = (void (*)(void)) fn;
- break;
- case GLU_ERROR:
- tobj->callbacks.error = (void (*)(GLenum)) fn;
- break;
- default:
- tobj->error=GLU_INVALID_ENUM;
- break;
- }
- }
-
-
-
- void gluDeleteTess( GLUtriangulatorObj *tobj )
- {
- if(tobj->error==GLU_NO_ERROR && tobj->contour_cnt)
- /* was gluEndPolygon called? */
- tess_call_user_error(tobj,GLU_TESS_ERROR1);
- /* delete all internal structures */
- delete_contours(tobj);
- free(tobj);
- }
-
-
- void gluBeginPolygon( GLUtriangulatorObj *tobj )
- {
- /*
- if(tobj->error!=GLU_NO_ERROR)
- return;
- */
- tobj->error = GLU_NO_ERROR;
- if(tobj->current_polygon!=NULL)
- {
- /* gluEndPolygon was not called */
- tess_call_user_error(tobj,GLU_TESS_ERROR1);
- /* delete all internal structures */
- delete_contours(tobj);
- }
- else
- {
- if((tobj->current_polygon=
- (tess_polygon *)malloc(sizeof(tess_polygon)))==NULL)
- {
- tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
- return;
- }
- tobj->current_polygon->vertex_cnt=0;
- tobj->current_polygon->vertices=
- tobj->current_polygon->last_vertex=NULL;
- }
- }
-
-
- void gluEndPolygon( GLUtriangulatorObj *tobj )
- {
- /*tess_contour *contour_ptr;*/
-
- /* there was an error */
- if(tobj->error!=GLU_NO_ERROR) goto end;
-
- /* check if gluBeginPolygon was called */
- if(tobj->current_polygon==NULL)
- {
- tess_call_user_error(tobj,GLU_TESS_ERROR2);
- return;
- }
- tess_test_polygon(tobj);
- /* there was an error */
- if(tobj->error!=GLU_NO_ERROR) goto end;
-
- /* any real contours? */
- if(tobj->contour_cnt==0)
- {
- /* delete all internal structures */
- delete_contours(tobj);
- return;
- }
- tess_find_contour_hierarchies(tobj);
- /* there was an error */
- if(tobj->error!=GLU_NO_ERROR) goto end;
-
- tess_handle_holes(tobj);
- /* there was an error */
- if(tobj->error!=GLU_NO_ERROR) goto end;
-
- /* if no callbacks, nothing to do */
- if(tobj->callbacks.begin!=NULL && tobj->callbacks.vertex!=NULL &&
- tobj->callbacks.end!=NULL)
- {
- if(tobj->callbacks.edgeFlag==NULL)
- tess_tesselate(tobj);
- else
- tess_tesselate_with_edge_flag(tobj);
- }
-
- end:
- /* delete all internal structures */
- delete_contours(tobj);
- }
-
-
- void gluNextContour( GLUtriangulatorObj *tobj, GLenum type )
- {
- if(tobj->error!=GLU_NO_ERROR)
- return;
- if(tobj->current_polygon==NULL)
- {
- tess_call_user_error(tobj,GLU_TESS_ERROR2);
- return;
- }
- /* first contour? */
- if(tobj->current_polygon->vertex_cnt)
- tess_test_polygon(tobj);
- }
-
-
- void gluTessVertex( GLUtriangulatorObj *tobj, GLdouble v[3], void *data )
- {
- tess_polygon *polygon=tobj->current_polygon;
- tess_vertex *last_vertex_ptr;
-
- if(tobj->error!=GLU_NO_ERROR)
- return;
- if(polygon==NULL)
- {
- tess_call_user_error(tobj,GLU_TESS_ERROR2);
- return;
- }
- last_vertex_ptr=polygon->last_vertex;
- if(last_vertex_ptr==NULL)
- {
- if((last_vertex_ptr=(tess_vertex *)
- malloc(sizeof(tess_vertex)))==NULL)
- {
- tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
- return;
- }
- polygon->vertices=last_vertex_ptr;
- polygon->last_vertex=last_vertex_ptr;
- last_vertex_ptr->data=data;
- last_vertex_ptr->location[0]=v[0];
- last_vertex_ptr->location[1]=v[1];
- last_vertex_ptr->location[2]=v[2];
- last_vertex_ptr->next=NULL;
- last_vertex_ptr->previous=NULL;
- ++(polygon->vertex_cnt);
- }
- else
- {
- tess_vertex *vertex_ptr;
-
- /* same point twice? */
- if(fabs(last_vertex_ptr->location[0]-v[0]) < EPSILON &&
- fabs(last_vertex_ptr->location[1]-v[1]) < EPSILON &&
- fabs(last_vertex_ptr->location[2]-v[2]) < EPSILON)
- {
- tess_call_user_error(tobj,GLU_TESS_ERROR6);
- return;
- }
- if((vertex_ptr=(tess_vertex *)
- malloc(sizeof(tess_vertex)))==NULL)
- {
- tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
- return;
- }
- vertex_ptr->data=data;
- vertex_ptr->location[0]=v[0];
- vertex_ptr->location[1]=v[1];
- vertex_ptr->location[2]=v[2];
- vertex_ptr->next=NULL;
- vertex_ptr->previous=last_vertex_ptr;
- ++(polygon->vertex_cnt);
- last_vertex_ptr->next=vertex_ptr;
- polygon->last_vertex=vertex_ptr;
- }
- }
-
-
- static void delete_contours(GLUtriangulatorObj *tobj)
- {
- tess_polygon *polygon=tobj->current_polygon;
- tess_contour *contour,*contour_tmp;
- tess_vertex *vertex,*vertex_tmp;
-
- /* remove current_polygon list - if exists due to detected error */
- if(polygon!=NULL)
- {
- if (polygon->vertices)
- {
- for(vertex=polygon->vertices;vertex!=polygon->last_vertex;)
- {
- vertex_tmp=vertex->next;
- free(vertex);
- vertex=vertex_tmp;
- }
- free(vertex);
- }
- free(polygon);
- tobj->current_polygon=NULL;
- }
- /* remove all contour data */
- for(contour=tobj->contours;contour!=NULL;)
- {
- for(vertex=contour->vertices;vertex!=contour->last_vertex;)
- {
- vertex_tmp=vertex->next;
- free(vertex);
- vertex=vertex_tmp;
- }
- free(vertex);
- contour_tmp=contour->next;
- free(contour);
- contour=contour_tmp;
- }
- tobj->contours=tobj->last_contour=NULL;
- tobj->contour_cnt=0;
- }
-
-
-
-